AWS CDK(Cloud Development Kit)を使用したカスタムリソースの利用
1 はじめに
CX事業本部の平内(SIN)です。
CloudFormationのリソースタイプとして用意されていないものは、カスタムリソースを使用します。
カスタムリソースでlambdaを使用すれば、ちょっと、トリッキーなので注意が必要ですが、たいがい何でもできてしまいます。
今回は、AWS CDKでカスタムリソース(Lambda)を使用する方法を確認してみました。
ちなみに、lambdaは、S3に置く方法とインラインで記述する方法の2種類がありますが、カスタムリソースの応答オブジェクトがcfn-responseモジュールで簡単に返せるインラインでの設置となってます。
2 スタック
スタック生成のコードです。
カスタムリソースは、cfn.CustomResource()で作成できます。providerにインラインのLambda、そして、パラメータは、propertiesから送ることができます。
cdk_custom_resource_lambda.ts
import cdk = require('@aws-cdk/core'); import cfn = require('@aws-cdk/aws-cloudformation'); import lambda = require('@aws-cdk/aws-lambda'); import fs = require('fs'); export class CdkCustomResourceStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const customResourse = new cfn.CustomResource(this, 'function', { provider: cfn.CustomResourceProvider.lambda(new lambda.SingletonFunction(this, 'singleton', { functionName: "customResourceLambdaFunction", uuid: '7731874a-3a77-80d5-cd8e-6350510edf90', code: new lambda.InlineCode(fs.readFileSync('lambda/index.js', { encoding: 'utf-8' })), handler: 'index.handler', timeout: cdk.Duration.seconds(300), runtime: lambda.Runtime.NODEJS_8_10 })), properties: {"Message": "bod boy"} }); new cdk.CfnOutput(this, "response", { value: customResourse.getAtt('Response').toString() }); } } const app = new cdk.App(); new CdkCustomResourceStack(app, 'CdkCustomResourceLambdaStack');
カスタムリソースに送ったパラメータを、再び戻り値で受け取って出力しています。
3 カスタムリソース
カスタムリソースのLambdaです。
cfn-responseモジュールを使用して、レスポンスを生成しています。
CDKからのパラメータは、 event['ResourceProperties'] で受け取り、send()の第4パラメータで戻り値を返すことができます。
すいません、今回は試していませんが、event['RequestType'] で、Create/Delete/Updateに対応した処理も記述可能のようです。
"use strict"; const cfnresponse = require('cfn-response'); exports.handler = (event, context) => { console.log(JSON.stringify(event)); console.log(JSON.stringify(context)); const params = event['ResourceProperties']; // Papameters const _requestType = event['RequestType']; // Create, Delete, Update try { const data = { 'Response': 'Your message: ' + params.Message }; cfnresponse.send(event, context, cfnresponse.SUCCESS, data); } catch (error) { console.log(error); cfnresponse.send(event, context, cfnresponse.FAILED, {}); } };
4 サンプル
サンプルをGitHubに置きました。名前等の競合がなければ、下記の手順で利用可能です。
- ダウンロード
$ git clone https://github.com/furuya02/CdkCustomResourceLambda.git $ cd CdkCustomResourceLambda
- デプロイ
$ yarn $ tsc $ cdk synth $ cdk deploy Do you wish to deploy these changes (y/n)? y
- スタックの削除
cdk destroy
5 注意
今回、色々試していて気がついた点を列挙させて下さい。
これは、AWS CDKに限った話では無いですが、カスタムリソースでLambdaを使用する場合、下記の点に注意すると作業がスムーズに進むかも知れません。
- インラインで記述するので、特別なモジュールの読み込みはできない
- Lambdaの定義は、inlineで行う code: new lambda.InlineCode(fs.readFileSync()
- AWS CDKからパラメータで送ったキー名が、ラージキャメルに変更される(ログから渡されているパラメータを確認したほうが良い)
- カスタムリソースのLambdaは、確実に応答オブジェクトを返す send()
- カスタムリソースのLambdaは、asyncで起動すると、応答オブジェクトが返る前にLambdaが終了するので正常にスタックが作成されない(CREATE_IN_PROGRESSで止まる)
- send()メソッドの第4パラメータは、Deleteでも必要
- カスタムリソースのLambdaでNode10.xは使えない
- cdkの下の.gitignoreには、.jsが入っているので、インライン用のjsを対象外にしておかない、Githubへのpushで洩れる
CREATE_IN_PROGRESSで止まってしまったら、削除して1時間ぐらい放置する(すぐには消せない)[2019/08/03]↑こちらについては、下記で対策可能であると@toriclsさんから教えて頂きました。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-lambda-resource-delete/
6 最後に
今回は、カスタムリソースをAWS CDKで書いてみました。 失敗して、CREATE_IN_PROGRESSのまま返ってこなくなると、悲しくなります。